/**
 * Copyright (c) 2016 Lenovo Group
 * All Rights Reserved.
 * 
 * Project Name:event-recorder
 * Create Time: 2016年4月13日 下午5:08:04
 */
package com.lenovo.lmrp.server.eventrecorder.spi;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import com.lenovo.lmrp.api.constant.BizErrorCode;
import com.lenovo.lmrp.api.model.entity.EngineerPO;
import com.lenovo.lmrp.api.model.view.EngineerRankingVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lenovo.lmrp.api.constant.StatisticsType;
import com.lenovo.lmrp.api.eventrecorder.ITicketStatisticsQuery;
import com.lenovo.lmrp.api.model.RestResponse;
import com.lenovo.lmrp.api.model.entity.CitygpsPO;
import com.lenovo.lmrp.api.model.view.MapStatisticsVO;
import com.lenovo.lmrp.api.model.view.TicketStatisticVO;
import com.lenovo.sdc.framework.annotation.RestService;
import com.lenovo.sdc.framework.dao.ADaoFactory;
import com.lenovo.sdc.framework.dao.ICommonDAO;
import com.lenovo.sdc.framework.dao.IQueryExecutor;
import com.lenovo.sdc.framework.dao.ICommonDAO.FinderEnum;
import com.lenovo.sdc.framework.dao.RecordFilter;
import com.lenovo.sdc.framework.util.CommonUtil;
import com.lenovo.sdc.framework.util.Condition;
import com.lenovo.sdc.framework.util.Condition.OperatorEnum;
import com.lenovo.sdc.framework.util.exception.ErrorCode;
import com.lenovo.sdc.framework.util.exception.TraceableException;

/**
 * @author zhangzheng
 *
 */

@RestService
@Path("/event/v1")
@Consumes("application/json;charset-utf-8")
@Produces("application/json;charset-utf-8")
public class TicketStatisticsQueryImpl implements ITicketStatisticsQuery {

    private static final Logger logger = LoggerFactory.getLogger(TicketStatisticsQueryImpl.class);

    //城市列表
    @Override
    public RestResponse<List<CitygpsPO>> getCityList(String itsmcode) {
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmcode)) {
            List<CitygpsPO> cities = dao.filteByCondition(CitygpsPO.class, new RecordFilter());
            return new RestResponse<List<CitygpsPO>>(0, "ok", cities);
        }
        catch (Exception exp) {
            TraceableException.writeLog(ErrorCode.DB_QUERY_FAILED, "failed query city list.", exp);
            return new RestResponse<List<CitygpsPO>>(1, "failed", null);
        }
    }

    @Override
    public RestResponse<List<MapStatisticsVO>> statisticsByAll(String itsmcode, int statisticstype, Map<String, String> fields) {
        logger.debug("query parameters : itsmcode is {},statisticstype is {},fields is {}",
            itsmcode, statisticstype, fields);
        List<TicketStatisticVO> queryResult = new ArrayList<>();
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmcode)) {
            StatisticsType type = StatisticsType.values()[statisticstype];

            RecordFilter filter = new RecordFilter();
            IQueryExecutor executor = dao.getRegisteredFinder(FinderEnum.SQL);
            String[] projects = null;
            String[] periodRange = null;
            if (Objects.nonNull(fields)) {
                if (CommonUtil.nonNullAndEmpty(fields.get("project"))) {
                    projects = fields.get("project").split(",");
                }
                //获得日期区间
                periodRange = formatPeriod(fields.get("period"));
            }//查询时间默认当前月
            else {
            	periodRange = formatPeriod(null);
            }
            //查询工程师量
            if (type == StatisticsType.ENGINEER) {
                if (Objects.nonNull(projects)) {
                    filter.addCondition(
                        new Condition<String, Object>("concat(c.id,'-',c.name)", projects, OperatorEnum.IN));
                }
                queryResult = executor.findByNamedQuery("udq_engineercountbyall", filter);
            } //查询工单量
            else if (type == StatisticsType.TICKET) {
                
                if (Objects.nonNull(periodRange) && periodRange.length == 2) {
                    filter.addCondition(new Condition<String, Object>("a.sumtime", periodRange, OperatorEnum.BETWEEN));
                }
                //包含项目查询
                if (Objects.nonNull(projects)) {
                    filter.addCondition(new Condition<String, Object>("a.project", projects, OperatorEnum.IN));
                    queryResult = executor.findByNamedQuery("udq_ticketcountbyallcontainproject", filter);
                } //不包含项目
                else {
                    queryResult = executor.findByNamedQuery("udq_ticketcountbyall", filter);
                }
            }
        }
        catch (Exception exp) {
            TraceableException.writeLog(ErrorCode.DB_QUERY_FAILED, "failed statistics for mapview", exp);
            return new RestResponse<List<MapStatisticsVO>>(1, "query failed.", null);
        }
        return new RestResponse<List<MapStatisticsVO>>(0, "ok", transformVO(queryResult));
    }

    @Override
    public RestResponse<List<MapStatisticsVO>> statisticsByCity(String itsmcode, Map<String, String> fields) {
        logger.debug("query parameters : itsmcode is {},fields is {}",itsmcode, fields);
        List<TicketStatisticVO> queryResult = new ArrayList<>();
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmcode)) {
            RecordFilter filter = new RecordFilter();
            IQueryExecutor executor = dao.getRegisteredFinder(FinderEnum.SQL);
            if (Objects.nonNull(fields)) {
            	//获得日期区间
                String[] periodRange = formatPeriod(fields.get("period"));
                filter.addCondition(new Condition<String, Object>("a.sumtime", periodRange, OperatorEnum.BETWEEN));
                //项目列表
                if (CommonUtil.nonNullAndEmpty(fields.get("project"))) {
                    filter.addCondition(new Condition<String, Object>("a.project", fields.get("project").split(","), OperatorEnum.IN));
                }
                //城市
                if (CommonUtil.nonNullAndEmpty(fields.get("city"))) {
                    filter.addCondition(new Condition<String, Object>("a.city", "%" + fields.get("city") + "%", OperatorEnum.LIKE));
                }
                
            }//时间默认当前月
            else {
            	//获得日期区间
                String[] periodRange = formatPeriod(null);
                filter.addCondition(new Condition<String, Object>("a.sumtime", periodRange, OperatorEnum.BETWEEN));
            }
            queryResult = executor.findByNamedQuery("udq_ticketcountByAddress", filter);
        }
        catch (Exception exp) {
            TraceableException.writeLog(ErrorCode.DB_QUERY_FAILED, "failed query ticket by city", exp);
            return new RestResponse<List<MapStatisticsVO>>(1, "failed query", null);
        }
        return new RestResponse<List<MapStatisticsVO>>(0, "ok", transformVO(queryResult));
    }

    @Override
    public RestResponse<List<MapStatisticsVO>> statisticsByRegion(String itsmcode, Map<String, String> fields) {
        logger.debug("query parameters : itsmcode is {},fields is {}",itsmcode, fields);

        List<TicketStatisticVO> queryResult = new ArrayList<>();
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmcode)) {
            RecordFilter filter = new RecordFilter();
            IQueryExecutor executor = dao.getRegisteredFinder(FinderEnum.SQL);
            if (Objects.nonNull(fields)) {
            	//获得日期区间
                String[] periodRange = formatPeriod(fields.get("period"));
                filter.addCondition(new Condition<String, Object>("a.sumtime", periodRange, OperatorEnum.BETWEEN));
                //项目列表
                if (CommonUtil.nonNullAndEmpty(fields.get("project"))) {
                    filter.addCondition(new Condition<String, Object>("a.project", fields.get("project").split(","), OperatorEnum.IN));
                }
                //经纬度区间
                if (CommonUtil.nonNullAndEmpty(fields.get("positionleft")) && CommonUtil.nonNullAndEmpty(fields.get("positionright"))) {
                    String positionleft = fields.get("positionleft");
                    String positionright = fields.get("positionright");
                    
                    filter.addCondition(new Condition<String, Object>("b.longitude",
                        new Double[] { Double.valueOf(positionleft.split(",")[0]), Double.valueOf(positionright.split(",")[0]) }, OperatorEnum.BETWEEN));
                    filter.addCondition(new Condition<String, Object>("b.latitude",
                        new Double[] { Double.valueOf(positionright.split(",")[1]), Double.valueOf(positionleft.split(",")[1]) }, OperatorEnum.BETWEEN));
                }
            }//默认当前月
            else {
            	//获得日期区间
                String[] periodRange = formatPeriod(null);
                filter.addCondition(new Condition<String, Object>("a.sumtime", periodRange, OperatorEnum.BETWEEN));
            }
            logger.debug("where is {}",filter.getParameters());
            queryResult = executor.findByNamedQuery("udq_ticketcountByAddress", filter);
        }
        catch (Exception exp) {
            TraceableException.writeLog(ErrorCode.DB_QUERY_FAILED, "failed query ticket by city", exp);
            return new RestResponse<List<MapStatisticsVO>>(1, "failed query", null);
        }
        return new RestResponse<List<MapStatisticsVO>>(0, "ok", transformVO(queryResult));
    }

    @Override
    public RestResponse<List<EngineerRankingVO>> engineerRankingByEvaluate(String itsmcode, String engineerid,Map<String, String> fields) {
        logger.debug("query parameters : itsmcode is {},fields is {}",itsmcode, fields);
        List<EngineerRankingVO> rankingVOs = new ArrayList<>();
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmcode)) {
            IQueryExecutor executor = dao.getRegisteredFinder(FinderEnum.SQL);
            RecordFilter recordFilter = new RecordFilter();
            //获得日期区间
            String[] periodRange = null;
            if (Objects.nonNull(fields)) {
                periodRange = formatPeriod(fields.get("period"));
            }
            else {
                periodRange = formatPeriod(null);
            }
            logger.debug("where is {}",recordFilter.getParameters());
            recordFilter.addCondition(new Condition<String, Object>("a.sumtime",periodRange,OperatorEnum.BETWEEN));

            rankingVOs = executor.findByNamedQuery("udq_engineerranking",recordFilter);
            //判断是否包含当前工程师。
            boolean containself = false;
            for (EngineerRankingVO rankingVO : rankingVOs) {
                if (rankingVO.getEngineerid().equals(engineerid)) {
                    containself = true;
                    break;
                }
            }
            //当前工程师未进入排名，获取当前工程师的数据添加到列表末尾
            if (!containself) {
                recordFilter.addCondition(new Condition<String, Object>("a.engineerid",engineerid));
            }
            List<EngineerRankingVO> mySelfRank = executor.findByNamedQuery("udq_engineerranking",recordFilter);
            if (mySelfRank.isEmpty()) {
                EngineerPO engineerPO = dao.get(EngineerPO.class,engineerid);
                if (engineerid != null) {
                    EngineerRankingVO engineerRankingVO = new EngineerRankingVO();
                    engineerRankingVO.setEngineerid(engineerid);
                    engineerRankingVO.setFullname(engineerPO.getFullName());
                    engineerRankingVO.setRankvalue(0);
                    rankingVOs.add(engineerRankingVO);
                }
            }
            else {
                rankingVOs.addAll(mySelfRank);
            }

        }
        catch (Exception exp) {
            TraceableException .writeLog(ErrorCode.DB_QUERY_FAILED,"failed query engineers ranking info.",exp);
            return new RestResponse<List<EngineerRankingVO>>(1,"failed query",null);
        }
        return new RestResponse<List<EngineerRankingVO>>(0,"ok",rankingVOs);
    }

    private List<MapStatisticsVO> transformVO(List<TicketStatisticVO> queryResult) {

        List<MapStatisticsVO> statisticsVOs = new ArrayList<>();
        if (Objects.nonNull(queryResult)) {
            for (TicketStatisticVO tsv : queryResult) {
                MapStatisticsVO vo = new MapStatisticsVO();
                vo.setName(tsv.getCity() == null ? tsv.getAddress() : tsv.getCity());
                vo.setCount(tsv.getCount());
                Map<String, Object> point = new HashMap<>();
                point.put("lng", tsv.getLongitude());
                point.put("lat", tsv.getLatitude());
                vo.setPoint(point);
                statisticsVOs.add(vo);
            }
        }
        return statisticsVOs;
    }

    private String[] formatPeriod(String period) {

        String[] periodRange = new String[2];
        //时间为空 默认为当月
        if (CommonUtil.isNullOrEmpty(period)) {
            periodRange[0] = CommonUtil.getDateFormatter("yyyy-MM-01").format(new Date());
            periodRange[1] = CommonUtil.getDateFormatter("yyyy-MM-31").format(new Date());
        } //按月查
        else if (period.length() == 7) {
            periodRange[0] = period + "-01";
            periodRange[1] = period + "-31";
        } //按年查
        else if (period.length() == 4) {
            periodRange[0] = period + "-01-01";
            periodRange[1] = period + "-12-31";
        }
        return periodRange;
    }
}
